package cn.javaxc.mvcwork.util.io;
import cn.javaxc.mvcwork.util.common.StringUtils;
import java.io.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.*;



public class PrivateString {

  private Key key = null;


  
  public PrivateString() {
  }


  
  public PrivateString(String file) {
    key = PrivateString.generateEncodedKeyFile(file);
  }


  
  public void setKey(Key tmp) {
    this.key = tmp;
  }

  public void setKeyFromHexEncoding(String hex) throws Exception {
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
    DESKeySpec keySpec = new DESKeySpec(Hex.decodeHex(hex.toCharArray()));
    key = keyFactory.generateSecret(keySpec);
  }


  
  public Key getKey() {
    return key;
  }

  public String getKeyAsHexEncoding() {
    return new String(Hex.encodeHex(key.getEncoded()));
  }


  
  public static synchronized Key generateEncodedKeyFile(String filename) {
    try {
      File file = new File(filename);
      if (!file.exists()) {
        // Generate key
        KeyGenerator generator = KeyGenerator.getInstance("DES");
        generator.init(56, new SecureRandom());
        Key key = generator.generateKey();
        // Save key
        String hex = new String(Hex.encodeHex(key.getEncoded()));
        StringUtils.saveText(filename, hex);
      }
      return PrivateString.loadEncodedKey(filename);
    } catch (Exception e) {
      e.printStackTrace(System.out);
    }
    return null;
  }

  public static Key loadEncodedKey(String keyFilename) throws IOException {
    File file = new File(keyFilename);
    return loadEncodedKey(file);
  }

  public static Key loadEncodedKey(File keyFilename) throws IOException {
    String hex = StringUtils.loadText(keyFilename);
    try {
      SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
      DESKeySpec keySpec = new DESKeySpec(Hex.decodeHex(hex.toCharArray()));
      return keyFactory.generateSecret(keySpec);
    } catch (Exception e) {
      throw new IOException(e.getMessage());
    }
  }

  public static Key loadSerializedKey(String keyFilename) throws IOException {
    File file = new File(keyFilename);
    return loadSerializedKey(file);
  }

  
  public static Key loadSerializedKey(File keyFile) throws IOException {
    try {
      ObjectInputStream in = new ObjectInputStream(
          new FileInputStream(keyFile));
      Key key = (Key) in.readObject();
      in.close();
      return key;
    } catch (Exception e) {
      System.out.println(
          "PrivateString-> Error loading key at: " + keyFile);
      throw new IOException(e.getMessage());
    }
  }


  
  public static String encrypt(Key key, String inString) {
    try {
      Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
      cipher.init(Cipher.ENCRYPT_MODE, key);
      byte[] inputBytes = inString.getBytes("UTF8");
      byte[] outputBytes = cipher.doFinal(inputBytes);
      return new String(Base64.encodeBase64(outputBytes, true));
    } catch (Exception e) {
      return null;
    }
  }


  
  public static String decrypt(Key key, String inString) {
    try {
      //Security.addProvider(new com.sun.crypto.provider.SunJCE());

      Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
      cipher.init(Cipher.DECRYPT_MODE, key);

      byte[] inputBytes = Base64.decodeBase64(inString.getBytes("UTF8"));
      byte[] outputBytes = cipher.doFinal(inputBytes);

      return new String(outputBytes, "UTF8");
    } catch (Exception e) {
      System.out.println(e.toString());
      return null;
    }
  }


  
//  public static String encryptAsymmetric(String keyFilename, String inString) throws IOException {
//    Key key = PrivateString.loadSerializedKey(keyFilename);
//    return PrivateString.encryptAsymmetric(key, inString);
//  }
//
//
//  
//  public static String encryptAsymmetric(File keyFile, String inString) throws IOException {
//    Key key = PrivateString.loadSerializedKey(keyFile);
//    return PrivateString.encryptAsymmetric(key, inString);
//  }


  
//  public static String encryptAsymmetric(Key publicKey, String inString) {
//    try {
//      Security.addProvider(
//          new org.bouncycastle.jce.provider.BouncyCastleProvider());
//
//      Cipher cipher = Cipher.getInstance("RSA/None/OAEPPadding", "BC");
//      cipher.init(Cipher.ENCRYPT_MODE, publicKey);
//      byte[] inputBytes = inString.getBytes("UTF8");
//      byte[] outputBytes = cipher.doFinal(inputBytes);
//
//      return new String(Base64.encodeBase64(outputBytes, true));
//    } catch (Exception e) {
//      return null;
//    }
//  }


  
//  public static String decryptAsymmetric(String keyFilename, String inString) throws IOException {
//    Key key = PrivateString.loadSerializedKey(keyFilename);
//    return PrivateString.decryptAsymmetric(key, inString);
//  }


  
//  public static String decryptAsymmetric(Key privateKey, String inString) {
//    try {
//      Security.addProvider(
//          new org.bouncycastle.jce.provider.BouncyCastleProvider());
//
//      Cipher cipher = Cipher.getInstance("RSA/None/OAEPPadding", "BC");
//      cipher.init(Cipher.DECRYPT_MODE, privateKey);
//
//      byte[] inputBytes = Base64.decodeBase64(inString.getBytes("UTF8"));
//      byte[] outputBytes = cipher.doFinal(inputBytes);
//
//      return new String(outputBytes, "UTF8");
//    } catch (Exception e) {
//      System.out.println(e.toString());
//      return null;
//    }
//  }


  
  public static void main(String args[]) {

    try {
      if (args.length == 0) {
        System.out.println("[encrypt or decrypt] [key] [string]");
      } else {
        String method = args[0];
        String keyFile = args[1];
        String text = args[2];

        File thisFile = new File(keyFile);
        Key key = null;
        if (!thisFile.exists()) {
          key = generateEncodedKeyFile(keyFile);
        } else {
          key = loadEncodedKey(keyFile);
        }
        if ("encrypt".equals(method)) {
          System.out.println(PrivateString.encrypt(key, text));
        } else {
          System.out.println(PrivateString.decrypt(key, text));
        }
      }

    } catch (Exception ex) {
      ex.printStackTrace(System.out);
    }
  }

}
